#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>
#include<mpi.h>
#include<unistd.h>
#include"defs.h"

int main(int argc, char **argv){
	int rank, size;
	int liminf, limsup;
	int vector_size = VECTOR_SIZE;
	int k;
	real piecesize;
	real *vec;	
	real receivedresult,parcialresult,totalresult = 0.0;
	time_t timer1, timer2;
	char hostname[100];
	MPI_Status status;

	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &size);

	if (rank==0){
		timer1 = time(NULL);
	}

	if (argc>1){
		vector_size = atoi(argv[1]);
	}
	vec = (real*)malloc(sizeof(real)*vector_size);

	if (argc>2){
		init_vector(vec,vector_size,atoi(argv[2]));
	}else{	
		init_vector(vec,vector_size,1.0);
	}

	//subdivide o calculo da soma entre os processos de forma reversa
	piecesize = (vector_size+1)/size;
	liminf = (int)ceil((size-(rank+1))*piecesize);
	limsup = (int)floor((size-(rank))*piecesize);

	if (rank==0){
		limsup = vector_size;  //garante que o processo 0 calcula os elementos excedentes da distribuicao
		parcialresult = parcialsquaresum(vec, liminf, limsup);
		totalresult += parcialresult;
		for (k=1;k<size;k++){
			MPI_Recv(&receivedresult, 1, MPI_LONG_DOUBLE, k, 1001, MPI_COMM_WORLD, &status); //recebe resultado de cada processo
			totalresult += receivedresult;
		}
		printf("Resultado total: %llf\n", totalresult); //resultado da soma
		printf("Norma do vetor: %.10llf\n", sqrt(totalresult));  //resultado da norma
		timer2 = time(NULL);
		printf("tabela %lf\n",difftime(timer2,timer1));  //resultado da norma	
	}else{
		parcialresult = parcialsquaresum(vec, liminf, limsup);
		MPI_Send(&parcialresult, 1, MPI_LONG_DOUBLE, 0, 1001, MPI_COMM_WORLD); //envia dados para o processo 0
	}

	//resultado parcial da soma
	gethostname(hostname,99);
	printf("(%d,%d) %s: Calculando soma dos quadrados do vector da posicao %d a %d = %.2llf\n", rank, size, hostname, liminf, limsup, parcialresult);

	MPI_Finalize();
	free(vec);
}
